package netty.demo_01_simple;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.util.CharsetUtil;


/**
 * Netty快速入门实例-TCP服务
 * 自定义的 服务器端 的 Handler，Pipeline 中的处理器
 *
 * @author chenyuan
 * @date 2020/11/6 17:58
 */

/**
 * 1. 自定义一个 Handler 需要继承 Netty 规定好的某个 处理器适配器
 * 2. 这时自定义的 Handler ，才能称为一个 Handler
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
	/** 读取数据的事件（可以读取客户端发送的消息）
	 *
	 * @param ctx 上下文对象，包含 管道、通道、地址
	 * @param msg 客户端发送的消息，默认是 Object 类型
	 * @throws Exception
	 */
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		System.out.println("服务器读取线程的 Name ：" + Thread.currentThread().getName());
		System.out.println("【Server】： ctx" + ctx);
		System.out.println("Channel 和 Pipeline 关系:");
		Channel channel = ctx.channel();
		// 本质是一个双向链表
		ChannelPipeline pipeline = ctx.pipeline();


		// 将 msg 转换成 ByteBuffer
        /*
            说明 :
            1. 注意这个是 ByteBuf ，是 io.netty.buffer 包下的，不是 NIO 下的 Buffer
            2. ByteBuf 比 Buffer 的性能更高一点
         */
		ByteBuf buf = (ByteBuf) msg;
		// 把 buf 转成 UTF8 格式的字符串
		System.out.println("客户端发送的 msg ：" + buf.toString(CharsetUtil.UTF_8));
		System.out.println("客户端地址 ：" + ctx.channel().remoteAddress());
	}

	/**
	 * 数据读取完毕后，返回消息给客户端
	 * @param ctx
	 * @throws Exception
	 */
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		// 把数据写入缓冲区，并刷新缓冲区
		// 一般来说，需要对这个发送的消息进行编码
		ctx.writeAndFlush(Unpooled.copiedBuffer("Hello,客户端", CharsetUtil.UTF_8));
	}

	/**
	 * 处理异常
	 * @param ctx
	 * @param cause
	 * @throws Exception
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		// 关闭通道
		ctx.channel().close();
	}
}
